package com.csyf.manager.utils;

import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HttpHelper {

    public static final String default_charset = "UTF-8";
    public static final Integer default_timeout = 30000;
    public static final Integer default_socket = 30000;

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);

    public static String deGet(String url) {
        return doGet(url, null);
    }

    public static String doGet(String url, Map<String, String> params) {
        return doGet(url, params, default_charset);
    }

    /**
     * Http GET 请求
     *
     * @param url
     * @param params
     * @param charset
     * @return
     */
    public static String doGet(String url, Map<String, String> params, String charset) {

        try {
            LOGGER.debug("HttpHelper doGet URL [{}]", url);
            String requestUrl = "";
            if (null == params) {
                requestUrl = url;
            } else {
                Set<Map.Entry<String, String>> entries = params.entrySet();
                StringBuffer buffer = new StringBuffer();
                for (Map.Entry<String, String> map : entries) {
                    buffer.append(map.getKey()).append("=").append(map.getValue()).append("&");
                }
                String substring = buffer.substring(0, buffer.length() - 1);
                requestUrl = url + "?" + substring;
                LOGGER.debug("HttpGet params: [{}]", substring);
            }

            HttpGet httpGet = new HttpGet(requestUrl);
            httpGet.setConfig(getConfig());
            return doexcete(httpGet, charset);
        } catch (Exception e) {
            LOGGER.error("HttpHelper doGet Exception", e);
        } finally {

        }
        return null;
    }

    public static String doPostForm(String url) {
        return doPostForm(url, null);
    }

    public static String doPostForm(String url, Map<String, String> data) {
        return doPostForm(url, data, default_charset);
    }

    /**
     * doPost form 表单提交
     *
     * @param url
     * @param data
     * @param charset
     * @return
     */
    public static String doPostForm(String url, Map<String, String> data, String charset) {

        try {
            LOGGER.debug("HttpHelper doPostForm URL [{}]", url);

            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());

            if (null == data) {

            } else {
                LOGGER.debug("HttpHelper doPostForm params [{}]", data.toString());
                List<NameValuePair> list = new ArrayList<>();
                Set<Map.Entry<String, String>> entries = data.entrySet();
                for (Map.Entry<String, String> map : entries) {
                    list.add(new BasicNameValuePair(map.getKey(), map.getValue()));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(list, charset));
            }
            return doexcete(httpPost, charset);
        } catch (Exception e) {
            LOGGER.error("HttpHelper doPostForm Exception", e);
        }
        return null;
    }

    public static String doPostJson(String url, String jsonString) {
        return doPostJson(url, jsonString, default_charset);
    }

    /**
     * @param url
     * @param jsonString
     * @param charset
     * @return
     */
    public static String doPostJson(String url, String jsonString, String charset) {

        try {

            LOGGER.debug("HttpHelper doPostJson URL [{}]", url);
            LOGGER.debug("HttpHelper doPostJson params [{}]", jsonString);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());

            StringEntity entity = new StringEntity(jsonString.toString(), charset);
            entity.setContentEncoding(charset);
            entity.setContentType("application/json");

            httpPost.setEntity(entity);
            return doexcete(httpPost, charset);

        } catch (Exception e) {
            LOGGER.error("HttpHelper doPostJson Exception", e);
        }

        return null;
    }

    public static String doPostFormJson(String url, String jsonString) {
        return doPostJson(url, jsonString, default_charset);
    }

    /**
     * @param url
     * @param jsonString
     * @param charset
     * @return
     */
    public static String doPostFormJson(String url, String jsonString, String charset) {

        try {

            LOGGER.debug("HttpHelper doPostJson URL [{}]", url);
            LOGGER.debug("HttpHelper doPostJson params [{}]", jsonString);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());

            StringEntity entity = new StringEntity(jsonString.toString(), charset);
            entity.setContentEncoding(charset);
            entity.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(entity);
            return doexcete(httpPost, charset);

        } catch (Exception e) {
            LOGGER.error("HttpHelper doPostJson Exception", e);
        }

        return null;
    }

    /**
     * @param url
     * @param params
     * @return
     */
    public static String doPostXml(String url, String params) {
        return doPostXml(url, params, default_charset);
    }

    /**
     * @param url
     * @param jsonString
     * @param charset
     * @return
     */
    public static String doPostXml(String url, String jsonString, String charset) {

        try {

            LOGGER.debug("HttpHelper doPostJson URL [{}]", url);
            LOGGER.debug("HttpHelper doPostJson params [{}]", jsonString);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());

            StringEntity entity = new StringEntity(jsonString.toString(), charset);
            entity.setContentEncoding(charset);
            entity.setContentType("application/xml");

            httpPost.setEntity(entity);
            return doexcete(httpPost, charset);

        } catch (Exception e) {
            LOGGER.error("HttpHelper doPostJson Exception", e);
        }

        return null;
    }

    private static RequestConfig getConfig() {
        return RequestConfig.custom().setConnectTimeout(default_timeout).setSocketTimeout(default_socket).build();
    }

    private static String doexcete(HttpUriRequest httpUriRequest, String charset) throws Exception {

        String httpsScheme = "https";
        CloseableHttpClient aDefault = null;
        if (httpsScheme.equals(httpUriRequest.getURI().getScheme())) {
            aDefault = createSSLInsecureClient();
        } else {
            aDefault = HttpClients.createDefault();
        }

        CloseableHttpResponse execute = aDefault.execute(httpUriRequest);
        String string = EntityUtils.toString(execute.getEntity(), charset);
        aDefault.close();
        return string;
    }


    /**
     * 创建 SSL连接
     *
     * @return
     * @throws GeneralSecurityException
     */
    private static CloseableHttpClient createSSLInsecureClient() throws Exception {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();

            SSLConnectionSocketFactory sslSf = new SSLConnectionSocketFactory(sslContext);

            return HttpClients.custom().setSSLSocketFactory(sslSf).build();

        } catch (GeneralSecurityException e) {
            throw e;
        }
    }

    /**
     * @Title: submitPost
     * @Description: java.net实现 POST方法提交
     * @param @param url String
     * @param @param paramContent String 拼装好的参数串
     * @param @param charSet string
     * @param @param connTimeOut int
     * @param @param SoTimeOut int
     * @param @return    设定文件
     * @return String    返回类型
     * @throws
     */
    public static String submitPost(String url, String paramContent,String charSet, int connTimeOut,int soTimeOut) {
        StringBuffer message = null;
        java.net.URLConnection connection = null;
        java.net.URL reqUrl = null;
        OutputStreamWriter reqOut = null;
        InputStream in = null;
        BufferedReader br = null;
        String param = paramContent;
        String identifier = System.currentTimeMillis() + "";
        if(null==charSet||"".equals(charSet)){
            charSet="GBK";
        }
        try {
            message = new StringBuffer();//创建对象接收响应信息
            reqUrl = new java.net.URL(url);
            connection = reqUrl.openConnection();//创建连接
            connection.setReadTimeout(soTimeOut);//设置读取数据超时时间
            connection.setConnectTimeout(connTimeOut);//设置连接地址超时时间
            connection.setDoOutput(true);//使用post方式的时候，需要使用 URL 连接进行输出，所以设定为true
            reqOut = new OutputStreamWriter(connection.getOutputStream(),charSet);
            reqOut.write(param);//将参数信息添加到输出流中
            reqOut.flush();//刷新该流的缓冲
            int charCount = -1;
            in = connection.getInputStream();
            br = new BufferedReader(new InputStreamReader(in, charSet));//设定收取响应字符的编码格式
            while ((charCount = br.read()) != -1) {
                message.append((char) charCount);//将响应信息添加到message对象中
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return "EXCEPTION";
        } finally {
            try {
                //关闭打开的输入流和输出流
                in.close();
                reqOut.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return message.toString();
    }


}